昨天我們安裝後有試跑一下 flutter run
,而今天我們就要來好好講講這個預設專案到底有什麼東西。
我們先從檔案結構來說明一下
這裡有幾個比較重要的資料夾
其中 android 及 ios 和 web 都是我們需要額外開啟什麼功能或者打包相關的設定才有機會碰到,以我的經驗就是一些有關版本及權限問題或者firebase相關的東西有去更動過裡面的檔案,不然應該是沒什麼機會需要去動。
所以剩的就是 lib 及 test 這兩個資料夾。 test 是存放「測試」的資料夾像是Unit testing及Widget tests,而 lib 就是主要存放我們程式碼的地方。
接下來讓我們來了解一下 lib 裡的 main.dart 到底做了哪些事情。
第一眼會先看到 main()
這個function它是整個 dart code 的進入點。
裡面會執行一個function runApp
,簡單來說runApp
就是將我們的 widget 繪製到螢幕上的一個API,所以裡面放了一個 widget MyApp()
接下來看 MyApp
到底做了哪些事情。
首先看到 extends StatelessWidget
,說明了MyApp
是一個 StatelessWidget
。在 Flutter 中不考慮第三套件的話,UI相關widget基本上就是 StatelessWidget
及 StatefullWidget
這兩種,它們最大的差異是一個有狀態一個沒有,至於什麼是「狀態」我們等遇到了再好好說明。
說回到StatelessWidget
基本上我們的 widget 都是用 class
來宣告,所以會看到這個 MyApp
的 constructor
const MyApp({Key? key}) : super(key: key);
這裏有一個optional named parameter Key? key
,這個 key 的作用基本上是為了確保重新渲染後widget 能夠保持我們預期中的狀態而設定的,但如果只是純粹的UI顯示而沒有什麼CRUD的操作通常 key
是可以不用去管的。
接下來會看到 widget 中的重點
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
這個 @override
就是要 implement 我們從 StatelessWidget
(這是一個 abstract class)拿到的 build
method 。
他的 return type 是 Widget
所以會看到我們在大括號中 return 了一個 MaterialApp
,它包含了title、theme 及 route 的相關設定,而這裡的 home
就是default route的意思,所以 home
接了一個widget MyHomePage
至於 router
參數之後的範例會在說明。
簡而言之這算是一個 flutter/material 提供的一個App入口,如果你不用MaterialApp
是可以的但通常都會使用,即使不是用flutter/material 提供的也有可能會是其他第三方套件提供,像是 getx
就有一個 GetMaterialApp
作為入口。
繼續往下看到 MyHomePage
的實作
會發現這時是 extends StatefulWidget
也就是所謂有「狀態」的widget,有一個跟StatelessWidget
長的差不多的 constructor 然後多了一個 named parameter title
也就是接從上面 MaterialApp
傳下來的 'Flutter Demo Home Page'
。
再來會看到 implement createState
這個 method ,但createState
要認真解釋它到底做了哪些事情就要深入到flutter的渲染原理,所以這裡只要知道他是創造StatefulWidget
的 instance時會呼叫的method 。
接下來看 _MyHomePageState
這東西,基本上可以想像成是這個 StatefulWidget
UI描述及狀態管理的集合體。
這裡的 _counter
就是所謂的「狀態」,我們可以透過 setState
來做更新狀態,但到底什麼是「狀態」,我覺得是一個我們在互動中所產生的暫時結果。依這個例子來說我按下按鈕他會有一個結果來表示是現在的數字加一,但當我重新整理這一切會回到預設值。
而大部分有牽扯「狀態管理」的程式通常就蘊含了我們怎麼更新狀態數值、這個狀態數值怎麼跟我們的畫面連動等等議題。
以StatefulWidget
來說,我們調用了setState
來更新一個值時,會有一個流程將新的結果渲染到畫面上。所以當你把 setState
拿掉。只剩這樣時
void _incrementCounter() {
_counter++;
}
你會發現畫面怎麼按都不會更新。
至於 build
裡的東西,主要都是UI顯示相關的事情,就留到明天與其他常用widget一起說明了。